今天講一下有關class(類別)的繼承:沒有使用繼承的class,我們一般稱為"base class",繼承通常是這樣使用:
首先我們先宣告一個base class:
class userInformation {
var currentUser = String()
var information: String {
return "當前使用者為 \(currentUser)"
}
func showAllUsers() {
print("none")
}
}
然後我們宣告他的子類
class User1: userInformation {
var isOnline = false
}
如此一來,User1就是userInformation的子類(SubClass),而userInformation就是User1的父類,他會繼承父類的一切東西,例如currentUser跟information,當然在子類別裡,你可以去定義一些東西,譬如我就定義了一個"使用者是否在線上"的布林值,然後我們用下列方法把值取出來並顯示在終端機上
let allen = User1()
allen.isOnline = true
allen.currentUser = "allen"
print("使用者狀態: \(allen.information)")
上面我就對我子類別定義的"使用者是否在線上"對他的值的進行修改,當然子類別可以再被其他類別繼承,譬如這樣:
class Allen: User1 {
var currentNumberOfUser = 1
}
然後一樣,我們去設定他的值,並打印出來,記得前面的要註解掉或刪除掉,然後我們可以看到,我在新的類別同樣也宣告一個新的變數叫currentNumberOfUser,我們一樣可以對他進行值得修改
let allen = Allen()
allen.isOnline = true
allen.currentNumberOfUser = 1
allen.currentUser = "allen"
print("顯示當前使用者: \(allen.information)")
從上面程式碼,我們可以看到"isOnline"還是可以修改的,且多了一個"currentNumberOfUser",因為我們Allen這個類別繼承了User1類別~
重寫方法(Overriding),我們可以重寫的方式去重新定義子類的東西,例如這樣:
override func showAllUsers() {
print("使用者數:\(currentNumberOfUser)")
}
}
然後我們把他打印出來:
allen.showAllUsers()
把這段程式碼加在我們的子類裡面,代表我們對 function "showAllUsers", 進行了重寫,原本應該要顯示的是"none",重寫後變成"使用者數:1"結果如下:
重寫屬性,譬如我們有個父類跟一個子類:
//父類
class temperature {
var Temperature = 0.0
var description: String {
return "當前溫度:"
}
func dosomethingFunction() {
//do something
}
}
//子類
class currentTemperature: temperature {
override var Temperature: Double {
get {
return 36.5
}
set {
print(newValue)
}
}
// do something
}
接著我們把他打印出來:
let student1 = currentTemperature()
print(student1.description)
student1.Temperature = 37.0
可以注意到,我們設定一個新的值給他,是37.0,這樣我們就對Temperature進行了屬性重寫。
補充:
當我們子類要繼承的時候,無論繼承來的屬性是存儲型(let)的還是計算型(var)的屬性,子類並不知道繼承來的屬性是存儲型的還是計算型的(譬如:Temperature)它只知道繼承來的屬性會有一個名字和類型。所以你在重寫一個屬性時,必需將它的名字和類型都寫出來。然後我們可以自訂一個getter跟一個setter,當你使用setter作為重寫屬性的一部分,那你也必須提供一個getter,可以注意到上面的getter我們設定的值是 36.5 ,這是一個默認的值,譬如我們把"student1.Temperature = 37.0"這行程式碼,換成:
print(student1.Temperature)
結果如下:
這時候如果你不想為getter去提供一個默認的值,我們可以透過
return super.someProperty
這樣的方式來傳遞繼承得值,而someProperty就是我們要重寫的屬性的名子,譬如我們最一開始的程式碼:
class userInformation {
var currentUser = String()
var information: String {
return "當前使用者為 \(currentUser)"
}
func showAllUsers() {
print("none")
}
}
class User: userInformation {
var currentNumberOfUser = 1
var isOnline = false
}
class Allen: User {
override var information: String {
return super.information + " 使用者數量為:\(currentNumberOfUser)位"
}
}
我們就把information的屬性重寫了~
重寫屬性觀察器,首先我們先了解什麼是屬性觀察器,屬性觀察器(property observer)會監控和回應屬性值的變化,每次屬性被設置新的值都會呼叫屬性觀察器,譬如我們希望使用者輸入密碼不能有特定的字符,或是我們規定他要大寫,我們就可以透過屬性觀察器,去把多餘的字符刪除,或是幫忙轉化成大寫,我們先做一個簡單的轉換大小寫的屬性觀察器:
class upperCased {
var name = String() {
willSet(name) {
print("要轉換成大寫的字串:\(name)")
}
didSet {
if (name == name.lowercased()) {
self.name = name.uppercased()
print(name)
}
}
}
}
let lowerCased = upperCased()
lowerCased.name = "allen"
//結果:
//要轉換成大寫的字串:allen
//ALLEN
willSet 會在該值被存儲之前被調用
didSet 會在一個新值被存儲後被調用
接下來我們試看看重寫屬性觀察器:
class Tom: User {
override var currentUser: String {
didSet{
self.currentNumberOfUser = currentNumberOfUser + 1
}
}
override var information: String {
return super.information + " 使用者數量為:\(currentNumberOfUser)位"
}
}
結果:
最後如果我們如果要防止重寫的話:
在方法、屬性或者下標腳本的關鍵字前寫 final (譬如 final var , final func , final class func , final subscript )。